#include "core.h"
#include "xStream.h"

BOOL check_big_endian()
{
	union {
		int i;
		char c;
	}x={1};
	CGsStream::m_bBigEndian = (x.c == 1);
	return CGsStream::m_bBigEndian;
}

void ConvertEndian(void* pData, U32 dwLen)
{
	if(!CGsStream::m_bBigEndian)
	{
		U8* pC = (U8*)pData;
		U32 nHalf = dwLen / 2;
		for (U32 i = 0; i < nHalf; ++i)
		{
			U8 t = pC[i];
			pC[i] = pC[dwLen-i-1];
			pC[dwLen-i-1] = t;
		}
	}
}

BOOL CGsStream::m_bBigEndian = FALSE;

CGsStream::CGsStream(U8 * pData, U32 nCurrentLen, U32 nMaxLen)
:m_iWriteCursor(nCurrentLen),m_iReadCursor(0),m_nCurrentSize(nCurrentLen),m_nTotalSize(nMaxLen),m_bOverFlow(FALSE),m_pStreamMem(NULL)
{
	m_pData = pData;//new U8[MAX_NETSTREAM_LEN];
}

CGsStream::CGsStream(StreamMem* pStreamMem)
:m_iReadCursor(0),m_bOverFlow(FALSE),m_pStreamMem(pStreamMem)
{
	m_pData = pStreamMem->byBuf;
	m_nTotalSize = pStreamMem->dwSize;
	m_iWriteCursor = m_nCurrentSize = pStreamMem->dwUsedSize;
}

StreamMem* CGsStream::ReAlloc(StreamMem& Src)
{
	StreamMem* pRet = m_pStreamMem;
	m_nTotalSize = Src.dwSize;
	memcpy(Src.byBuf, m_pStreamMem->byBuf, m_pStreamMem->dwUsedSize);
	m_pStreamMem = &Src;
	pRet->dwUsedSize = Src.dwUsedSize = m_nCurrentSize;
	m_pData = Src.byBuf;

	return pRet;
}

StreamMem* CGsStream::ReInit(StreamMem* pSrc)
{
	if(m_pStreamMem)
	{
		m_pStreamMem->dwUsedSize = m_nCurrentSize;
	}
	StreamMem* pRet = m_pStreamMem;
	m_nTotalSize = pSrc? pSrc->dwSize : 0;
	m_iReadCursor = 0;
	m_iWriteCursor = m_nCurrentSize = pSrc ? pSrc->dwUsedSize : 0;
	m_bOverFlow = FALSE;
	m_pStreamMem = pSrc;
	m_pData = pSrc ? pSrc->byBuf: NULL;

	return pRet;
}

CGsStream::~CGsStream(void)
{
}

BOOL CGsStream::Put(void * pData, U32 nLen)
{
	if( ( m_iWriteCursor + nLen >= m_nTotalSize ) || ( m_pData == NULL ) )
	{
		m_bOverFlow = TRUE;
		return FALSE;
	}

	memcpy(m_pData+m_iWriteCursor, pData, nLen);
	m_iWriteCursor	+= nLen;
	m_nCurrentSize = m_iWriteCursor;

	return TRUE;
}

BOOL CGsStream::Get(void * pDes,  U32 nLen)
{
	if( ( m_iReadCursor + nLen > m_nCurrentSize ) || ( m_pData == NULL ) )
	{
		m_bOverFlow = TRUE;
		return FALSE;
	}

	memcpy(pDes, m_pData+m_iReadCursor, nLen);
	m_iReadCursor	+= nLen;

	return TRUE;
}

CGsStream& CGsStream::operator<<(U8 value)
{
	Put(&value, sizeof(value));
	return *this;
}

CGsStream& CGsStream::operator<<(U16 value)
{
	ConvertEndian(&value, sizeof(value));

	Put(&value, sizeof(value));
	return *this;
}

CGsStream& CGsStream::operator<<(U32 value)
{
	ConvertEndian(&value, sizeof(value));

	Put(&value, sizeof(value));
	return *this;
}

CGsStream& CGsStream::operator<<(U64 value)
{
	ConvertEndian(&value, sizeof(value));

	Put(&value, sizeof(value));
	return *this;
}

CGsStream& CGsStream::operator<<(F32 value)
{
	ConvertEndian(&value, sizeof(value));

	Put(&value, sizeof(value));
	return *this;
}

CGsStream& CGsStream::operator<<(F64 value)
{
	ConvertEndian(&value, sizeof(value));

	Put(&value, sizeof(value));
	return *this;
}

CGsStream& CGsStream::operator<<(S8 value)
{
	Put(&value, sizeof(value));
	return *this;
}

CGsStream& CGsStream::operator<<(S16 value)
{
	ConvertEndian(&value, sizeof(value));

	Put(&value, sizeof(value));
	return *this;
}

CGsStream& CGsStream::operator<<(S32 value)
{
	ConvertEndian(&value, sizeof(value));

	Put(&value, sizeof(value));
	return *this;
}

CGsStream& CGsStream::operator<<(S64 value)
{
	ConvertEndian(&value, sizeof(value));

	Put(&value, sizeof(value));
	return *this;
}

CGsStream& CGsStream::operator>>(U8& value)
{
	Get(&value, sizeof(value));
	return *this;
}

CGsStream& CGsStream::operator>>(U16& value)
{
	Get(&value, sizeof(value));

	ConvertEndian(&value, sizeof(value));

	return *this;
}

CGsStream& CGsStream::operator>>(U32& value)
{
	Get(&value, sizeof(value));

	ConvertEndian(&value, sizeof(value));

	return *this;
}

CGsStream& CGsStream::operator>>(U64& value)
{
	Get(&value, sizeof(value));
	
	ConvertEndian(&value, sizeof(value));

	return *this;
}

CGsStream& CGsStream::operator>>(F32& value)
{
	Get(&value, sizeof(value));

	ConvertEndian(&value, sizeof(value));

	return *this;
}

CGsStream& CGsStream::operator>>(F64& value)
{
	Get(&value, sizeof(value));

	ConvertEndian(&value, sizeof(value));

	return *this;
}

CGsStream& CGsStream::operator>>(S8& value)
{
	Get(&value, sizeof(value));
	return *this;
}

CGsStream& CGsStream::operator>>(S16& value)
{
	Get(&value, sizeof(value));

	ConvertEndian(&value, sizeof(value));

	return *this;
}

CGsStream& CGsStream::operator>>(S32& value)
{
	Get(&value, sizeof(value));

	ConvertEndian(&value, sizeof(value));

	return *this;
}

CGsStream& CGsStream::operator>>(S64& value)
{
	Get(&value, sizeof(value));

	ConvertEndian(&value, sizeof(value));

	return *this;
}

CGsStream& CGsStream::operator<<(S8* value)
{
	Put(value, (S32)strlen((char*)value)+1);
	return *this;
}

CGsStream& CGsStream::operator>>(S8* value)
{
	Get(value, (S32)strlen((char*)(m_pData+m_iReadCursor))+1);
	return *this;
}

CGsStream& CGsStream::operator>>(bool& value)
{
	U8 t = 0;
	Get(&t, sizeof(t));
	value = t ? true : false;
	return *this;
}

CGsStream& CGsStream::operator<<(bool value)
{
	U8 t = value ? 1 : 0;
	Put(&t, sizeof(t));
	return *this;
}

CGsStream::CGsStream(const CGsStream& Src)
{
	m_iWriteCursor = Src.m_iWriteCursor;
	m_iReadCursor = Src.m_iReadCursor;
	m_pData = Src.m_pData;
	m_bOverFlow = Src.m_bOverFlow;
	m_nTotalSize = Src.m_nTotalSize;
	m_nCurrentSize = Src.m_nCurrentSize;
	m_pStreamMem = Src.m_pStreamMem;
}

void CGsStream::operator=(const CGsStream& Src)
{
	m_iWriteCursor = Src.m_iWriteCursor;
	m_iReadCursor = Src.m_iReadCursor;
	m_bOverFlow = Src.m_bOverFlow;
	m_nTotalSize = Src.m_nTotalSize;
	m_nCurrentSize = Src.m_nCurrentSize;
	m_pStreamMem = Src.m_pStreamMem;
	m_pData = Src.m_pData;
}

void CGsStream::Init(void)
{
	m_iWriteCursor = m_iReadCursor = 0;
}

//---------------------------------------------------------------------------------
xStream::xStream(U32 dwSize)
{
	m_pStreamMem = new StreamMem(dwSize);
	
	m_pData = m_pStreamMem->byBuf;
	m_nTotalSize = m_pStreamMem->dwSize;
	m_iWriteCursor = m_nCurrentSize = m_pStreamMem->dwUsedSize;
}

xStream::~xStream()
{
	if (m_pStreamMem)
	{
		delete m_pStreamMem;
		m_pStreamMem = NULL;
	}
}

U32 xStream::Shift(U32 dwSize)
{
	U32 dwLeftSize = SafeSub(m_nCurrentSize, dwSize);

	if (dwLeftSize)
	{
		memcpy(m_pData, m_pData+dwSize, dwLeftSize);
	}
	m_nCurrentSize = dwLeftSize;
	m_iWriteCursor = dwLeftSize;
	m_iReadCursor = SafeSub(m_iReadCursor, dwSize);
	if(m_pStreamMem)
	{
		m_pStreamMem->dwUsedSize = SafeSub(m_pStreamMem->dwUsedSize, dwSize);
	}

	return 0;
}

BOOL xStream::AddWriteSize(U32 dwSize)
{
	if( ( m_iWriteCursor + dwSize >= m_nTotalSize ) || ( m_pData == NULL ) )
	{
		m_bOverFlow = TRUE;
		return FALSE;
	}

	m_iWriteCursor	+= dwSize;
	m_nCurrentSize = m_iWriteCursor;

	if(m_pStreamMem)
	{
		m_pStreamMem->dwUsedSize += dwSize;
	}

	return TRUE;
}